package model;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.HashMap;
import java.util.List;
import model.behaviors.Behavior;
import model.viewModels.CenterModel;

/**
 * this class represents a figure
 */
public class Figure implements Positions {

    /**
     * constant for white figure color
     */
    public static final int WHITE = 0;
    /**
     * constant for black figure color
     */
    public static final int BLACK = 1;

    /**
     * true if the figure is selected
     */
    private boolean selected = false;

    /**
     * the is beaten or not
     */
    private boolean beaten;

    /**
     * the color of this figure, the BLACK and WHITE constants are intended for this
     */
    private int color;

    /**
     * the position of the figure, the position constants from positions interface are intended for this
     */
    private String position;

    /**
     * the start position of the figure, the position constants from positions interface are intended for this
     */
    private String startPosition;

    /**
     * the behavior of this figure
     */
    private Behavior behav;

    /**
     * constructor of a Figure
     * 
     * @param position
     *            the position of the figure
     * @param color
     *            the WHITE or BLACK constant to set the color
     * @param behav
     *            the behavior of this figure
     */
    public Figure( String position, int color, Behavior behav )
    {
	this.beaten = false;
	this.setPosition( position );
	this.color = color;
	this.behav = behav;
	this.startPosition = position;
    }

    /**
     * called when the figure is clicked, checks if the player clicked its color
     * 
     * @param match
     *            the match of this figure
     * @return true if figure is selected
     */
    public final boolean clicked( Match match )
    {
	// check if logged in user selected the right color
	boolean userIsPOne = CenterModel.loggedInUser == match.getPlayerOne();
	if ( ( userIsPOne && this.color == WHITE ) || ( !userIsPOne && this.color == BLACK ) )
	{
	    this.selected = !this.selected;
	}

	return this.selected;
    }

    /**
     * resets the position of this figure to their start position
     */
    public final void resetPosition()
    {
	this.position = this.startPosition;
    }

    /**
     * checks if this figure is white or not
     * 
     * @return a boolean value if this figure is white or not
     */
    public final boolean isWhite()
    {
	return this.color == WHITE;
    }

    /**
     * checks if this figure is black or not
     * 
     * @return a boolean value if this figure is black or not
     */
    public final boolean isBlack()
    {
	return this.color == BLACK;
    }

    /**
     * draws the this figure
     * 
     * @param fs
     *            size of a field on the playing field
     * @param g
     *            the graphics object to draw on
     * @param figMap
     *            reference to the list of unbeaten figures in this match
     * @param movesList
     *            reference to alle moves from this match
     */
    public final void drawFigure( int fs, Graphics g, HashMap<String, Figure> figMap, List<Move> movesList )
    {
	// calculate the position in numbers
	int x;
	int y;
	String count = "";
	// coordinates for a beaten figure
	if ( this.beaten )
	{
	    x = 0;
	    if ( this.position.matches( "B[WB]P." ) )
	    {
		y = 0;
		count = this.position.substring( 3 );
	    }
	    else if ( this.position.matches( "B[WB]T." ) )
	    {
		y = 1;
		count = this.position.substring( 3 );
	    }
	    else if ( this.position.matches( "B[WB]H." ) )
	    {
		y = 2;
		count = this.position.substring( 3 );
	    }
	    else if ( this.position.matches( "B[WB]B." ) )
	    {
		y = 3;
		count = this.position.substring( 3 );
	    }
	    else
	    {
		y = 4;
	    }
	}
	// coordinates for a figure on the board
	else
	{
	    x = this.position.charAt( 0 ) - 'A';
	    y = 7 - ( this.position.charAt( 1 ) - '1' );
	}

	g.drawImage( this.behav.getImg(), fs * x, fs * y, fs, fs, null );

	// draw the amount of beaten figures
	if ( count.length() > 0 )
	{
	    if ( Integer.valueOf( count ) > 1 )
	    {
		FontMetrics fm = g.getFontMetrics();
		count = "x" + count + " ";
		g.drawString( count, fs * ( x + 1 ) - fm.stringWidth( count ), fs * ( y + 1 ) - fm.getHeight() / 5 );
	    }
	}

	// draw selection
	if ( this.selected )
	{
	    Graphics2D g2d = (Graphics2D)g;
	    g2d.setColor( Color.CYAN );
	    int strokeWidth = (int)Math.round( fs * 0.1 );
	    g2d.setStroke( new BasicStroke( strokeWidth ) );
	    g2d.drawRect( fs * x + strokeWidth / 2, fs * y + strokeWidth / 2, fs - strokeWidth, fs - strokeWidth );
	    g2d.setColor( Color.BLACK );
	    this.behav.detectPossibleMoves( fs, g2d, figMap, this, movesList );
	}
    }

    /**
     * getter of selected
     * 
     * @return selected
     */
    public final boolean isSelected()
    {
	return this.selected;
    }

    /**
     * setter of selected
     * 
     * @param selected
     *            the selected to set
     */
    public final void setSelected( boolean selected )
    {
	this.selected = selected;
    }

    /**
     * getter of beaten
     * 
     * @return the beaten
     */
    public final boolean isBeaten()
    {
	return this.beaten;
    }

    /**
     * setter of beaten
     * 
     * @param beaten
     *            the beaten to set
     */
    public final void setBeaten( boolean beaten )
    {
	this.beaten = beaten;
    }

    /**
     * getter of color
     * 
     * @return the color
     */
    public final int getColor()
    {
	return this.color;
    }

    /**
     * getter of position
     * 
     * @return the position
     */
    public final String getPosition()
    {
	return this.position;
    }

    /**
     * setter of position
     * 
     * @param position
     *            the position to set
     */
    public final void setPosition( String position )
    {
	this.position = position;
    }

    /**
     * getter of x-position
     * 
     * @return position as Integer value
     */
    public final int getX()
    {
	return this.position.charAt( 0 ) - 'A';
    }

    /**
     * getter of y-position
     * 
     * @return position as Integer value
     */
    public final int getY()
    {
	return 7 - ( this.position.charAt( 1 ) - '1' );
    }

    /**
     * setter of behav
     * 
     * @param behav
     *            the behav to set
     */
    public final void setBehav( Behavior behav )
    {
	this.behav = behav;
    }

    /**
     * getter of behav
     * 
     * @return the behav
     */
    public final Behavior getBehav()
    {
	return this.behav;
    }

    /**
     * getter of startPosition
     * 
     * @return the startPosition
     */
    public final String getStartPosition()
    {
	return this.startPosition;
    }
}
